using System.Collections.Generic;
using System.Linq;
using System;
using System.Windows.Input;

namespace SolutionOrchestrator.Validators
{
	/// <summary>
	/// Fix is theoretically can be available. You should check FixesAvailable for actual results.
	/// </summary>
	public abstract class FixableViolation : Violation
	{
		protected void Revalidate()
		{
			_fixes = null;
			_fixesCount = -1;
			OnPropertyChanged(null);
		}

		IEnumerable<Fix> _fixes;

		public IEnumerable<Fix> FixesAvailable
		{
			get
			{
				return _fixes ?? (_fixes = FixesAvailableCore.ToArray());
			}
		}

//		IEnumerable<Fix> GetFixes()
//		{
//			var fixes = FixesAvailableCore.ToArray();
//			if (fixes.Where(x => x != null).Count() == 0)
//			{
//				return Enumerable.Empty<Fix>();
//			}
//			return fixes;
//		}

		protected abstract IEnumerable<Fix> FixesAvailableCore { get; }

		public bool DefaultExists
		{
			get { return DefaultFix != null; }
		}

		public ICommand ApplyDefaultFix
		{
			get { return new DelegateCommand(() => ApplyFix(DefaultFix)); }
		}

		public virtual Fix DefaultFix
		{
			get
			{
				var rec = FixesAvailable.Where(x =>x!=null&& x.Recommended).ToArray();
				if (rec.Length == 1)
				{
					return rec.Single();
				}
				//return FixesAvailable.Where(x => x.Recommended).FirstOrDefault();
				return null;
			}
		}

		int _fixesCount = -1;
		public override int FixesCount
		{
			get
			{
				return _fixesCount == -1 ? (_fixesCount = FixesAvailable.Where(x => x != null).Distinct().Count()) : _fixesCount;
			}
		}

		public void ApplyFix(Fix fix)
		{
			if (FixesAvailable.Contains(fix))
			{
				ApplyFixCore(fix);
			}
		}

		protected abstract void ApplyFixCore(Fix fix);
	}
}